package org.example.wax.manager;

import com.example.cabinet.lock.lib.LockControl;
import org.example.wax.constant.StatusConstant;
import org.example.wax.domain.NetworkStatus;
import org.example.wax.exception.ServiceException;
import org.example.wax.manager.listener.OnCabinetManagerListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class SixteenLock extends LockControl implements LockControl.OnLockControlListener {

    private static final Logger log = LoggerFactory.getLogger(SixteenLock.class);

    private String ip;
    private int index;
    private List<Integer> boxIndexes;
    private List<Integer> portIndexes;
    private Map<Integer, Integer> boxPortMap = new HashMap<>();
    private Map<Integer, Integer> portBoxMap = new HashMap<>();
    private int cabinetId;
    private NetworkStatus status = new NetworkStatus();
    private boolean lockControlBusy;
    private OnCabinetManagerListener listener;

    public SixteenLock(String ip, int index, int cabinetId, List<Integer> boxIndexes, List<Integer> portIndexes) {
        this.ip = ip;
        this.index = index;
        this.cabinetId = cabinetId;
        this.boxIndexes = boxIndexes;
        this.portIndexes = portIndexes;
        this.status.setIndex(index);
        this.status.setIp(ip);
        this.status.setStatus(StatusConstant.STATUS_DISCONNECTED);
        this.status.setBoxes(boxIndexes);
        this.setOnLockControlListener(this);
    }

    public String getIp() {
        return ip;
    }

    public int getCabinetId() {
        return cabinetId;
    }

    public NetworkStatus getStatus() {
        getOpened();
        return status;
    }

    public void setOnCabinetManagerListener(OnCabinetManagerListener listener) {
        this.listener = listener;
    }

    public void checkLayout() throws ServiceException {
        if (CollectionUtils.isEmpty(boxIndexes) || CollectionUtils.isEmpty(portIndexes)) {
            throw new ServiceException("箱门号或接入锁控板端口号不能为空");
        }
        if (boxIndexes.size() != portIndexes.size()) {
            throw new ServiceException("箱门号和接入锁控板端口号的长度不一致");
        }
        for (int i = 0; i < boxIndexes.size(); i++) {
            boxPortMap.put(boxIndexes.get(i), portIndexes.get(i));
            portBoxMap.put(portIndexes.get(i), boxIndexes.get(i));
        }
    }

    public List<Integer> getSelPorts(List<Integer> boxes) {
        List<Integer> selPorts = new ArrayList<>();
        for (Integer box : boxes) {
            if (boxPortMap.containsKey(box)) {
                selPorts.add(boxPortMap.get(box));
            }
        }
        return selPorts;
    }

    public int getBox(int port) {
        if (portBoxMap.containsKey(port)) {
            return portBoxMap.get(port);
        }
        return -1;
    }

    public void getOpened() {
        byte[] opened = new byte[60];
        List<Integer> openedBoxes = new ArrayList<>();
        if (getStatus(opened) == LockControl.SUCCESS) {
            for (int i = 0; i < 60; i++) {
                if (opened[i] == 1) {
                    int port = i + 1;
                    if (portBoxMap.containsKey(port)) {
                        openedBoxes.add(portBoxMap.get(port));
                    }
                }
            }
        }
        this.status.setOpened(openedBoxes);
    }

    public int connectEx() {
        int rc = connect(ip, 11000, cabinetId);
        if (rc == LockControl.SUCCESS) {
            this.status.setStatus(StatusConstant.STATUS_CONNECTED);
        }
        return rc;
    }

    public int disconnectEx() {
        int rc = disconnect();
        if (rc == LockControl.SUCCESS) {
            this.status.setStatus(StatusConstant.STATUS_DISCONNECTED);
        }
        return rc;
    }

    public boolean isLockControlBusy() {
        return lockControlBusy;
    }

    public void setLockControlBusy(boolean lockControlBusy) {
        this.lockControlBusy = lockControlBusy;
    }

    @Override
    public void onClosed(String ip, int port) {
        if (listener != null) {
            if (portBoxMap.containsKey(port)) {
                log.debug("onClosed: {}, {}, {}", this.ip, port, portBoxMap.get(port));
                listener.onClosed(portBoxMap.get(port));
            }
        }
    }
}
